#include "mandpoints.h"
#include <iostream>
#include <complex>

using namespace std;

int _tlx = 0;
int _tly = 0;
float _incPerPixel = 0;

#define MAXITERATIONS 100

MandPoints::MandPoints(int tlx, int tly, float incPerPixel, int sizex, int sizey)
{
	_tlx = tlx;
	_tly = tly;
	_incPerPixel = incPerPixel;
}

//
//Create an array to hold the points
//Array size = 3 * sizex * sizey
//For each point call translatePoint to get the complex number,
//then call getPoint which will return an integer. 
//
unsigned char* MandPoints::getPoints(int sizex, int sizey)
{
	unsigned char *points = new unsigned char[3*sizex*sizey];
	int index = 0;
	int x,y;
	for (y=0;y<sizey;y++)
	{
		for (x=0;x<sizex;x++)
		{
			std::complex<double> imag = translatePoint(x,y,_incPerPixel,_tlx,_tly);
			int escapeVal = getPoint(imag);
			if (escapeVal == 100)
			{ escapeVal = 0;} //for the case where we colour the pixels black
			int* colours = new int[3];
			colours = convertIntToRGB(escapeVal);
			points[index] = (unsigned char)colours[0];
			points[index+1] = (unsigned char)colours[1];
			points[index+2] = (unsigned char)colours[2];
			index = index + 3; 
		}
	}
	return points;
}

//
//Given an x,y point and increment per pixel,translate to
//A complex number
//
std::complex<double> MandPoints::translatePoint(int x, int y, float incPerPixel, int tlx, int tly)
{
	float real = 0.0;
	float imaginary = 0.0;
	real = tlx + (x*incPerPixel);
	imaginary = tly + (y*incPerPixel*-1);
	std::complex<double> c1(real,imaginary);
	return c1;
}

//
// Calculate the escape value of a point, if it reaches MAXITERATIONS, colour it
// black, otherwise colour it according to the iteration value
//
int MandPoints::getPoint(std::complex<double> point)
{
	std::complex<double> c = point;
	std::complex<double> z(0.0,0.0);
	
	int iterations = 0;
	
	for (iterations=1;iterations<MAXITERATIONS;iterations++)
	{
		z = pow(z,2) + c;
		if (abs(z) > 2)
			{ break; }
	}
	
	return iterations;
}

//
// Output an RGB value depending upon the int passed
//
int* MandPoints::convertIntToRGB(int colValue)
{
	int* retVal = new int[3];
	double frequency;
	double r,g,b;
	
	frequency = 75.0/MAXITERATIONS;

	r = sin(frequency*colValue + 0) * (127) + 128;
	g = sin(frequency*colValue + 2) * (127) + 128;
	b = sin(frequency*colValue + 4) * (127) + 128;	

	retVal[0] = floor(r);
	retVal[1] = floor(g);
	retVal[2] = floor(b);
	
	return retVal;
}
